import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { ROLES_KEY } from 'src/decorators/roles.decorators';
import { Role } from 'src/enum/roles.enum';
import { UserService } from 'src/user/user.service';

@Injectable()
export class RoleGuard implements CanActivate {
    constructor(
        private reflector: Reflector,
        private userService: UserService,
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        // 从jwt校验中 可以获取到userid ->  user实例 -> roles表

        /* 
        getAllAndMerge -> 合并
        getAllAndOveride -> 读取路由上的metadata
        */
        const requiredRoles = this.reflector.getAllAndMerge<Role[]>(ROLES_KEY, [
            context.getHandler(),
            context.getClass(),
        ]);
        /* 
        requireRoles 的返回结果是 roles.controller中 注入的
        @Roles(Role.Admin) 
        
        假设没有注入  那么直接通过校验
        */
        if (!requiredRoles.length) {
            return true;
        }
        
        
        // 如果注入了  
        // 1. 先去获取 用户携带token中的角色
        const req = context.switchToHttp().getRequest();
        const user = await this.userService.findByUsername(req.user.username);
        const roleIds = user.roles.map((o) => o.id);
        
        // 2. 去对比注入的角色 有没有token的角色
        const flag = requiredRoles.some((role) => roleIds.includes(role));
        
        // 3. 如何调试 比如用户lrq~~  加入注入的角色是test  
        // 那么 首先在enum中添加test角色 然后在控制器中 单独给某个接口注入 @Roles(Role.Test) 
        return flag;
    }
}
